package com.future.baselib.utils;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.text.TextUtils;

import com.future.baselib.entity.BaseResponse;
import com.future.baselib.inteface.HttpService;
import com.google.gson.Gson;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.scalars.ScalarsConverterFactory;


/**
 * Created by jniu on 2017/6/20.
 */

public class HttpRequest<T extends BaseResponse> {

    public static final String TAG = HttpRequest.class.getName();


    public static final String NETWORK_KEY = "1e56c95504a9a846e4c7043704a20f25";

    private static HttpService httpService;

    private static int readTimeout = 5;
    private static int writeTimeout = 60;

    private Context context;
    private String url;
    private File file;
    private List<String> mFilePaths;

    private TreeMap<String, Object> params;
    private TreeMap<String, String> fileParams;

    private OnNetworkListener<T> listener;

    public static HttpService getHttpService() {
        if (httpService == null) {
            httpService = initRetrofit();
        }
        return httpService;
    }

    private static HttpService initRetrofit() {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(readTimeout, TimeUnit.SECONDS)
                .writeTimeout(writeTimeout, TimeUnit.SECONDS)
                .readTimeout(readTimeout, TimeUnit.SECONDS)
                .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiCst.BASE_API)
                .addConverterFactory(ScalarsConverterFactory.create())
                .client(client)
                .build();

        return retrofit.create(HttpService.class);
    }

    public HttpRequest setTimeout(int readTimeout, int writeTimeout) {
        this.readTimeout = readTimeout;
        this.writeTimeout = writeTimeout;
        return this;
    }

    public HttpRequest with(Context context) {
        this.context = context;
        return this;
    }

    public HttpRequest addParam(String key, Object values) {
        if (values == null) {
            return this;
        }
        if (params == null) {
            params = new TreeMap<>();
        }
        params.put(key, values);
        return this;
    }


    public HttpRequest addFileParam(String key, String values) {
        if (values == null) {
            return this;
        }
        if (fileParams == null) {
            fileParams = new TreeMap<>();
        }
        fileParams.put(key, values);
        return this;
    }

    public HttpRequest addParams(TreeMap<String, Object> params) {
        if (this.params == null) {
            this.params = new TreeMap<>();
        }
        this.params.putAll(params);
        return this;
    }

    public HttpRequest setListener(OnNetworkListener listener) {
        this.listener = listener;
        return this;
    }

    public HttpRequest setApiCode(String url) {
        this.url = url;
        return this;
    }

    public HttpRequest setFile(File file) {
        this.file = file;
        return this;
    }

    public HttpRequest start(final T t) {
        if (context == null) {
            LogUtils.e(TAG, "context不能为空");
            if (listener != null)
                listener.onFail("", t);
            return this;
        }

        if (listener == null) {
            LogUtils.e(TAG, "请添加网络结果监听 Listener");
            return this;
        }

        if (checkNetworkStatus()) {
            Call<String> call = null;
            if (params == null)
                call = getHttpService().getData(url);
            else
                call = getHttpService().getData(params, url);

            call.enqueue(new Callback<String>() {
                @Override
                public void onResponse(Call<String> call, Response<String> response) {
                    t.parseJson(response.body(), response.code());
                    if (t.returnNo == 1) {
                        listener.onSuccess(t);
                    } else {
                        if (TextUtils.isEmpty(t.message)) {
                            listener.onFail(t.erroMessage, t);
                        } else
                            listener.onFail(t.message, t);
                    }
                }

                @Override
                public void onFailure(Call<String> call, Throwable throwable) {
                    listener.onFail(throwable.getMessage(), t);
                }
            });
        } else {
            listener.onFail("当前无网络连接，请检查网络后重试", t);
        }


        return this;
    }


    public HttpRequest upload(final T t) {
        if (context == null) {
            LogUtils.e(TAG, "context不能为空");
            if (listener != null)
                listener.onFail("", t);
            return this;
        }

        if (file == null) {
            LogUtils.e(TAG, "文件不能为空");
            return this;
        }

        if (listener == null) {
            LogUtils.e(TAG, "请添加网络结果监听 Listener");
            return this;
        }

        RequestBody requestFile =
                RequestBody.create(MediaType.parse("image/jpeg"), file);
        MultipartBody.Part body =
                MultipartBody.Part.createFormData("file", file.getName(), requestFile);

        if (checkNetworkStatus()) {
            getHttpService()
                    .uploadFile(url, fileParams, body)
                    .enqueue(new Callback<String>() {
                        @Override
                        public void onResponse(Call<String> call, Response<String> response) {
                            t.parseJson(response.body(), response.code());
                            if (t.returnNo == 1) {
                                listener.onSuccess(t);
                            } else {
                                if (TextUtils.isEmpty(t.message)) {
                                    listener.onFail(t.erroMessage, t);
                                } else
                                    listener.onFail(t.message, t);
                            }
                        }

                        @Override
                        public void onFailure(Call<String> call, Throwable throwable) {
                            listener.onFail(throwable.getMessage(), t);
                        }
                    });
        } else {
            listener.onFail("当前无网络连接，请检查网络后重试", t);
        }


        return this;
    }

    //上传多张图片
    public HttpRequest uploadMutiImage(final T t) {
        if (context == null) {
            LogUtils.e(TAG, "context不能为空");
            if (listener != null)
                listener.onFail("", t);
            return this;
        }

        if (mFilePaths == null || mFilePaths.size() == 0) {
            LogUtils.e(TAG, "文件不能为空");
            return this;
        }

        File[] files = new File[mFilePaths.size()];
        for (int i = 0; i < mFilePaths.size(); i++) {
            files[i] = new File(mFilePaths.get(i));
        }

        for (int i = 0; i < files.length; i++) {
            if (files[i] == null) {
                LogUtils.e(TAG, "文件不能为空");
                return this;
            }
        }

        RequestBody[] requestBodys = new RequestBody[files.length];
        for (int i = 0; i < files.length; i++) {
            requestBodys[i] = RequestBody.create(MediaType.parse("image/jpeg"), files[i]);
        }

        MultipartBody.Part[] parts = new MultipartBody.Part[requestBodys.length];
        for (int i = 0; i < files.length; i++) {
            parts[i] = MultipartBody.Part.createFormData("files[]", files[i].getName(), requestBodys[i]);
        }

        if (listener == null) {
            LogUtils.e(TAG, "请添加网络结果监听 Listener");
            return this;
        }
        if (checkNetworkStatus()) {
            getHttpService()
                    .uploadMutileImage(url, parts)
                    .enqueue(new Callback<String>() {
                        @Override
                        public void onResponse(Call<String> call, Response<String> response) {
                            t.parseJson(response.body(), response.code());
                            if (t.returnNo == 1) {
                                listener.onSuccess(t);
                            } else {
                                if (TextUtils.isEmpty(t.message)) {
                                    listener.onFail(t.erroMessage, t);
                                } else
                                    listener.onFail(t.message, t);
                            }
                        }

                        @Override
                        public void onFailure(Call<String> call, Throwable throwable) {
                            listener.onFail(throwable.getMessage(), t);
                        }
                    });
        } else {
            listener.onFail("当前无网络连接，请检查网络后重试", t);
        }
        return this;
    }

    public HttpRequest setMutiFilePath(List<String> filePaths) {
        this.mFilePaths = filePaths;
        return this;
    }

    /**
     * 生成请求token
     *
     * @param params
     * @return
     */
    public String getPostToken(TreeMap<String, String> params) {

        StringBuilder stringBuilder = new StringBuilder();
        Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            stringBuilder.append(entry.getValue());
        }
        return MD5.Md5(stringBuilder.append(NETWORK_KEY).toString());
    }

    /**
     * 请求参数封装成json串
     *
     * @param params
     * @return
     */
    public String postJson(TreeMap<String, String> params) {
        String json = new Gson().toJson(params);
        LogUtils.e("request", json);
        return json;
    }

    /**
     * 检查网络状态
     *
     * @return
     */
    public boolean checkNetworkStatus() {
        ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        Boolean isWifiConn = networkInfo.isConnected();

        networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
        Boolean isMobileConn = networkInfo.isConnected();

        return isMobileConn || isWifiConn;
    }

    public interface OnNetworkListener<T extends BaseResponse> {
        void onSuccess(T response);

        void onFail(String message, T response);
    }
}
